//引入http模块
var socketio = require('socket.io'),
	fs = require('fs'),
	https = require('http'),
	domain = require('domain'),
	redis = require('redis'),
	redisio = require('socket.io-redis'),
	request = require('request'),
	md5 = require('md5-node'),
	config = require('./config.js');

var d = domain.create();
d.on("error", function (err) {
	//console.log(err);
});

// var options = {
// key: fs.readFileSync('/usr/local/ssl/xxx.key'),
// cert: fs.readFileSync('/usr/local/ssl/xxx.crt')
// };
//var numscount=0;// 在线人数统计
var sockets = {};
var chat_history = {};  // 需要向直播间发送的消息集合
var chat_interval = {};  // 需要向直播间发送的消息集合的键，用于setTimeOut停止发送消息
var jinhua_interval = {};  // 金花游戏的定时器，用于停止游戏和断麦的时候停止
var jinhua_interTime = {};  // 金花游戏的定时器，用于下一轮发牌
var jinhua_info = {};  // 金花游戏的信息，用于断麦使用
/* 主播连麦关系 */
var LiveConnect = {};
var LiveConnect_pull = {};


// redis 链接
var clientRedis = redis.createClient(config['REDISPORT'], config['REDISHOST']);
clientRedis.auth(config['REDISPASS']);

// 开启socket服务
//var server = https.createServer(options,function(req, res) {
var server = https.createServer(function (req, res) {
	res.writeHead(200, {
		'Content-type': 'text/html;charset=utf-8'
	});

	//res.write("人数: " + numscount );
	res.end('服务开启' + config['socket_port']);
}).listen(config['socket_port'], function () {
	console.log('服务开启：' + config['socket_port']);
});

var field = [];  // 设置的过滤的字符
var io = socketio.listen(server, {
	pingTimeout: 60000,
	pingInterval: 25000
});
// console.log(io)

/* 多端口监听 内容统一 */
/* var pub = redis.createClient(config['REDISPORT'], config['REDISHOST'], { auth_pass: config['REDISPASS'] });
   var sub = redis.createClient(config['REDISPORT'], config['REDISHOST'], { auth_pass: config['REDISPASS'] });
 io.adapter(redisio({ pubClient: pub, subClient: sub })); */

/* 资源释放 */
//setInterval(function(){
//global.gc();
//console.log('GC done')
//}, 1000*30); 

io.on('connection', function (socket) {
	//console.log(FormatNowDate());
	//numscount++;

	var interval;
	console.log('连接成功', socket.id);

	// 获取服务端配置（获取后台设置的过滤的字符串）
	request(config['WEBADDRESS'] + "?service=Home.getFilterField", function (error, response, body) {
		if (error) {
			console.log(error);
			return;
		}
		if (!body) {
			console.log(body);
			return;
		}
		var res = evalJson(body);
		// console.log(body);
		//console.log(res.data.info);
		//console.log("sssss");
		field = res.data.info;
	});


	//进入房间
	socket.on('conn', function (data) {
		console.log('进入房间接受到的数据：', data);
		if (!data || !data.token) {
			return !1;
		}

		userid = data.uid;
		if (userid < 0 && userid == -9999) { //app端
			userid = data.mobileid;
			data.uid = data.mobileid;
			data.token = data.mobileid;
		}

		old_socket = sockets[userid];
		if (old_socket && old_socket != socket) {
			if (data.uid != data.roomnum && data.uid == old_socket.roomnum) {
				/* 进房间 但旧链接是 主播 */
				var data_str = '{"retmsg":"ok","retcode":"000000","msg":[{"msgtype":"1","_method_":"StartEndLive","action":"19","ct":"直播关闭"}]}';
				old_socket.emit('broadcastingListen', [data_str]);
			} else if (data.uid == data.roomnum && data.stream == old_socket.stream) {
				/* 主播重连 */
				old_socket.reusing = 1;
				//console.log("重用");
			} else if (data.uid == data.roomnum && data.stream != old_socket.stream) {
				/* 主播多端开播 */
				var data_str = '{"retmsg":"ok","retcode":"000000","msg":[{"msgtype":"1","_method_":"StartEndLive","action":"19","ct":"直播关闭"}]}';
				old_socket.emit('broadcastingListen', [data_str]);
			}
			old_socket.disconnect()
		}

		clientRedis.get(data.token, function (error, res) {
			console.log('解析token', data.token);
			//console.log(error);
			//console.log(res);
			if (error) {
				return;
			} else if (res == null) {
				console.log("[获取token失败]" + data.uid);

				var data_str2 = {
					"msg": [
						{
							"_method_": "conn",
							"action": "1",
							"uid": data.uid,
							"roomnum": data.roomnum,
							"stream": data.stream,
							"equipment": data.equipment,
							"isvideo": data.isvideo,
							"token": data.token,
							"ct": '进入房间解析token失败'
						}
					],
					"retcode": "000000",
					"retmsg": "ERR"
				};

				//process_msg(io, socket.roomnum, JSON.stringify(data_str2));
				socket.emit('conn', [JSON.stringify(data_str2)]);
				saveLog(JSON.stringify(data_str2));  // 保存日志
			} else {
				if (res != null) {
					var userInfo = evalJson(res);
					// console.log("用户进入直播间-----------"+res); 
					if (userInfo['id'] == data.uid) {
						console.log("[初始化验证成功]--" + data.uid + "---" + data.roomnum + '---' + data.stream);
						//获取验证token
						socket.token = data.token;
						socket.roomnum = data.roomnum;
						socket.stream = data.stream;
						socket.isvideo = data.isvideo ? 1 : 0;
						socket.nickname = userInfo['user_nickname'];
						socket.level = userInfo['level'];
						socket.avatar = userInfo['avatar'];
						socket.sign = Number(userInfo['sign']);
						socket.usertype = parseInt(userInfo['usertype']);
						socket.uid = data.uid;
						socket.reusing = 0;

						socket.join(data.roomnum);
						sockets[userid] = socket;
						socket.emit('conn', ['ok']);

						if (socket.roomnum != socket.uid && socket.uid > 0) {
							// 处理有时 无座驾信息会崩溃的问题
							var car_id = '0';
							var car_swf = '';
							var car_swftime = '';
							var car_words = '';
							if (userInfo.hasOwnProperty("car")) {
								var carinfo = userInfo['car'];
								if (carinfo.hasOwnProperty("id")) {
									car_id = carinfo['id'];
								}
								if (carinfo.hasOwnProperty("swf")) {
									car_swf = carinfo['swf'];
								}
								if (carinfo.hasOwnProperty("swftime")) {
									car_swftime = carinfo['swftime'];
								}
								if (carinfo.hasOwnProperty("words")) {
									car_words = carinfo['words'];
								}
							}

							var data_obj = {
								"msg": [
									{
										"_method_": "SendMsg",
										"action": "0",
										"ct": {
											"id": '' + userInfo['id'],
											"user_nickname": '' + userInfo['user_nickname'],
											"avatar": userInfo['avatar'],
											"avatar_thumb": userInfo['avatar_thumb'],
											"level": '' + userInfo['level'],
											"usertype": '' + userInfo['usertype'],
											"vip_type": '' + userInfo['vip']['type'],
											"guard_type": '' + userInfo['guard_type'],
											"liangname": '' + userInfo['liang']['name'],
											"car_id": '' + car_id,
											"car_swf": '' + car_swf,
											"car_swftime": '' + car_swftime,
											"car_words": '' + car_words
										},
										"msgtype": "0"
									}
								],
								"retcode": "000000",
								"retmsg": "OK"
							};
							process_msg(io, socket.roomnum, JSON.stringify(data_obj));
							if (socket.stream) {
								clientRedis.zadd('user_' + socket.stream, socket.sign, userInfo['id']);
							}
						}

						// sendSystemMsg(socket,"直播内容包含任何低俗、暴露和涉黄内容，账号会被封禁；安全部门会24小时巡查哦～");
						sendSystemMsg(socket, "欢迎来到直播间,我们倡导绿色直播。直播内容和封面有违法违规、色情低俗、抽烟喝酒、诱导欺诈、聚众闹事等行为账号会被封禁,网警24小时在线巡查哦！");
						return;
					} else {
						socket.disconnect();
					}
				}
			}

			socket.emit('conn', ['no']);
		});
	});

	socket.on('broadcast', function (data) {
		console.log('broadcast接收到的数据', data);
		if (socket.token == undefined) {
			console.log('broadcast接收到的用户token', socket.token);
			console.log('进入直播间用户token不存在，请先进入直播间');
			var data_str1 = {
				"msg": [
					{
						"_method_": "no_room",
						"action": "1",
						"uid": data.uid,
						"roomnum": data.roomnum,
						"stream": data.stream,
						"equipment": data.equipment,
						"isvideo": data.isvideo,
						"token": data.token,
						"ct": '进入直播间用户token不存在，请先进入直播间'
					}
				],
				"retcode": "000000",
				"retmsg": "ERR"
			};

			//process_msg(io, socket.roomnum, JSON.stringify(data_str1));
			socket.emit('broadcastingListen', [JSON.stringify(data_str1)]);
			//saveLog(JSON.stringify(data_str1));  // 保存日志
		}
		if (socket.token != undefined) {
			var dataObj = typeof data == 'object' ? data : evalJson(data);
			var msg = dataObj['msg'][0];
			var token = dataObj['token'];
			var method = msg['_method_'];
			var action = msg['action'];
			var data_str = typeof data == 'object' ? JSON.stringify(data) : data;
			console.log('  执行操作method：', method);
			switch (method) {

				// 发送消息：聊天
				case 'SendMsg': {
					dataObj['msg'][0]['ct'] = filter(dataObj['msg'][0]['ct']);
					clientRedis.hget("super", socket.uid, function (error, res) {
						if (error) return;

						// 如果是超管发送消息，且消息为空则为关闭
						if (res != null) {
							var data_str2 = {
								"msg": [
									{
										"_method_": "SystemNot",
										"action": "1",
										"ct": '' + dataObj['msg'][0]['ct'],
										"msgtype": "4"
									}
								],
								"retcode": "000000",
								"retmsg": "OK"
							};
							process_msg(io, socket.roomnum, JSON.stringify(data_str2));
							saveLog(data_str2);  // 保存日志
						} else {
							data_str = JSON.stringify(dataObj);
							clientRedis.hget(socket.roomnum + "shutup", socket.uid, function (error, res) {
								if (error) return;
								if (res != null) {
									var newData = dataObj;
									newData['retcode'] = '409002';
									socket.emit('broadcastingListen', [JSON.stringify(newData)]);
								} else {
									process_msg(io, socket.roomnum, data_str);
								}
							});
							saveLog(data_str);  // 保存日志
						}
					});
					break;
				}
				// 送礼
				case 'SendGift': {
					var gifToken = dataObj['msg'][0]['ct'];
					clientRedis.get(gifToken, function (error, res) {
						if (!error && res != null) {
							var sendGiftObj = evalJson(res);
							var len = sendGiftObj.length;

							console.log('礼物参数', sendGiftObj);
							//console.log(sendGiftObj);
							//console.log("长度:"+len);
							for (var i = 0; i < len; i++) {
								var resObj = sendGiftObj[i];

								dataObj['msg'][0]['ct'] = resObj;
								var ifpk = '0', pkuid1 = '0', pkuid2 = '0', pktotal1 = '0', pktotal2 = '0';

								//console.log('SendGift');
								//console.log(resObj);
								if (resObj['ispk'] == 1) {
									ifpk = '1';
									pkuid1 = '' + resObj['pkuid1'];
									pkuid2 = '' + resObj['pkuid2'];
									pktotal1 = '' + resObj['pktotal1'];
									pktotal2 = '' + resObj['pktotal2'];
									//console.log('pk');
								}

								dataObj['msg'][0]['ifpk'] = ifpk;
								dataObj['msg'][0]['pkuid1'] = pkuid1;
								dataObj['msg'][0]['pkuid2'] = pkuid2;
								dataObj['msg'][0]['pktotal1'] = pktotal1;
								dataObj['msg'][0]['pktotal2'] = pktotal2;

								// 全站礼物
								//console.log('dataObj');
								//console.log(dataObj);
								// (resObj['isplatgift']=='1')||
								if ((parseInt(resObj['lucktimes']) >= 500)) {
									var platdata_obj = {
										"msg": [
											{
												"_method_": "Sendplatgift",
												"action": "0",
												"giftcount": resObj['giftcount'],
												"giftname": resObj['giftname'],
												"lucktimes": resObj['lucktimes'],
												"luckcoin": resObj['luckcoin'],
												"uname": dataObj['msg'][0]['uname'],
												"livename": dataObj['msg'][0]['livename'],
												"liveuid": socket.roomnum,
												"stream": socket.stream,
												"msgtype": '0',
											}
										],
										"retcode": "000000",
										"retmsg": "OK"
									};

									console.log('全站礼物', platdata_obj);
									io.emit('broadcastingListen', [JSON.stringify(platdata_obj)]);
									// io.emit('broadcastingListen',['{"msg":[{"_method_":"Sendplatgift","action":"0","giftcount":"'+resObj['giftcount']+'","giftname":"'+resObj['giftname']+'","uname":"'+dataObj['msg'][0]['uname']+'","livename":"'+dataObj['msg'][0]['livename']+'","liveuid":"'+socket.roomnum+'","stream":"'+socket.stream+'","msgtype":"0"}],"retcode":"000000","retmsg":"OK"}']);
								}

								io.sockets.in(socket.roomnum).emit('broadcastingListen', [JSON.stringify(dataObj)]);
								if (pkuid2 > 0) {
									io.sockets.in(pkuid2).emit('broadcastingListen', [JSON.stringify(dataObj)]);
								}

								/* 幸运中奖 */
								if (resObj.isluck == 1 && resObj.isluckall == 1) {
									var data_luck = {
										"msg": [
											{
												"_method_": "luckWin",
												"action": "1",
												"uid": '' + msg.uid,
												"uname": '' + msg.uname,
												"uhead": '' + msg.uhead,
												"giftid": '' + resObj.giftid,
												"giftname": '' + resObj.giftname,
												"lucktimes": '' + resObj.lucktimes,
												"msgtype": "4"
											}
										],
										"retcode": "000000",
										"retmsg": "OK"
									};
									io.emit('broadcastingListen', [JSON.stringify(data_luck)]);
								}
								/* 幸运中奖 */

								/* 奖池升级 */
								if (resObj.isup == 1) {
									var data_up = {
										"msg": [
											{
												"_method_": "jackpotUp",
												"action": "1",
												"uplevel": '' + resObj.uplevel,
												"msgtype": "4"
											}
										],
										"retcode": "000000",
										"retmsg": "OK"
									};
									io.emit('broadcastingListen', [JSON.stringify(data_up)]);
								}
								/* 奖池升级 */

								/* 奖池中奖 */
								if (resObj.iswin == 1) {
									var data_win = {
										"msg": [
											{
												"_method_": "jackpotWin",
												"action": "1",
												"uid": '' + msg.uid,
												"uname": '' + msg.uname,
												"uhead": '' + msg.uhead,
												"wincoin": '' + resObj.wincoin,
												"msgtype": "4"
											}
										],
										"retcode": "000000",
										"retmsg": "OK"
									};
									io.emit('broadcastingListen', [JSON.stringify(data_win)]);

									var data_up = {
										"msg": [
											{
												"_method_": "jackpotUp",
												"action": "1",
												"uplevel": '0',
												"msgtype": "4"
											}
										],
										"retcode": "000000",
										"retmsg": "OK"
									};
									io.emit('broadcastingListen', [JSON.stringify(data_up)]);
								}
								/* 奖池中奖 */

							}

							clientRedis.del(gifToken);
						}
					});
					break;
				}
				//弹幕
				case 'SendBarrage': {
					var barragetoken = dataObj['msg'][0]['ct'];
					//console.log('aa:'+ JSON.stringify(dataObj['msg'][0]))
					//console.log(barragetoken)

					clientRedis.get(barragetoken, function (error, res) {
						//console.log(res)
						if (!error && res != null) {
							var resObj = evalJson(res);

							var con = resObj.content;
							var res = filter(con);
							resObj.content = res;

							dataObj['msg'][0]['ct'] = resObj;
							var data_str = JSON.stringify(dataObj);
							process_msg(io, socket.roomnum, data_str);
							clientRedis.del(barragetoken);
						}
					});
					break;
				}
				//用户和主播连麦
				case 'ConnectVideo': {
					//1：发起连麦；2；接受连麦；3:拒绝连麦；4：连麦成功通知；5.发起者断开连麦；6：主播断开连麦;7:主播正忙碌 8:主播无响应
					if (action == '5' || action == '6') {
						clientRedis.hget('ShowVideo', socket.roomnum, function (error, res) {
							if (error) {
								return !1;
							}
							if (!res) {
								return !1;
							}
							var res_j = JSON.parse(res);

							if (socket.uid == res_j['uid'] || socket.uid == socket.roomnum) {
								clientRedis.hdel('ShowVideo', socket.roomnum);
								process_msg(io, socket.roomnum, data_str);
							}
						});
					} else if (action == '2') {

						var touid = msg['touid'];
						//console.log(touid);
						//console.log('主播同意连麦');
						request(config['WEBADDRESS'] + "?service=Live.showVideo&uid=" + socket.uid + "&token=" + socket.token + "&touid=" + touid + "&pull_url=''", function (error, response, body) {
							//console.log('showVideo');
							//console.log(body);
						});
						process_msg(io, socket.roomnum, data_str);
					} else {
						process_msg(io, socket.roomnum, data_str);
					}
					break;
				}
				//点亮
				case 'light': {
					process_msg(io, socket.roomnum, data_str);
					break;
				}
				//切换房间收费
				case 'changeLive': {
					process_msg(io, socket.roomnum, data_str);
					break;
				}
				//更新映票
				case 'updateVotes': {
					process_msg(io, socket.roomnum, data_str);
					break;
				}
				//关闭直播
				/*case 'CloseLive' :{
					if(socket.usertype == 50 ){
						process_msg(io,socket.roomnum,data_str);
					}
					break;
				}*/
				//踢人
				case 'KickUser': {
					process_msg(io, socket.roomnum, data_str);
					break;
				}
				//禁言
				case 'ShutUpUser': {
					process_msg(io, socket.roomnum, data_str);
					break;
				}
				//超管关播
				case 'stopLive': {
					clientRedis.hget("super", socket.uid, function (error, res) {
						if (error) return;
						if (res != null) {
							process_msg(io, socket.roomnum, 'stopplay');
						}
					});
					break;
				}
				//恢复发言
				case 'ResumeUser': {
					if (socket.usertype == 50 || socket.usertype == 40) {
						process_msg(io, socket.roomnum, data_str);
					}
					break;
				}
				//设置/取消管理员
				case 'setAdmin': {
					if (socket.usertype == 50) {
						process_msg(io, socket.roomnum, data_str);
					}
					break;
				}
				// 开始、结束直播
				case 'StartEndLive': {
					if (socket.usertype == 50) {
						socket.broadcast.to(socket.roomnum).emit('broadcastingListen', [data_str]);
					} else {
						clientRedis.get("LiveAuthority" + socket.uid, function (error, res) {
							if (error) return;
							if (parseInt(res) == 5 || parseInt(res) == 1 || parseInt(res) == 2) {
								socket.broadcast.to(socket.roomnum).emit('broadcastingListen', [data_str]);
							}
						})
					}
					break;
				}
				//购买守护
				case 'BuyGuard': {
					process_msg(io, socket.roomnum, data_str);
					break;
				}
				//送红包
				case 'SendRed': {
					process_msg(io, socket.roomnum, data_str);
					break;
				}
				//主播和主播连麦
				case 'LiveConnect': {
					if (socket.roomnum != socket.uid) {
						//非主播不能操作
						return !1;
					}
					var pkuid = msg['pkuid'];
					var pkpull = msg['pkpull'];

					//1：发起连麦；2；接受连麦;3:拒绝连麦;4：连麦成功通知;5.手动断开连麦;7:对方正忙碌 8:对方无响应 9:主播繁忙（游戏）
					if (action == '1') {
						// console.log('发起连麦');
						// console.log(FormatNowDate());
						// console.log(socket.uid+'---'+pkuid);
						// console.log(pkpull);
						// console.log('LiveConnect_pull--'+socket.uid+'-----'+pkpull);
						LiveConnect_pull[socket.uid] = pkpull;
						clientRedis.hset('LiveConnect_pull', socket.uid, pkpull);
					}
					if (action == '2') {
						// console.log('接受连麦');
						// console.log(FormatNowDate());
						// console.log(socket.uid+'---'+pkuid);
						// console.log(pkpull);
						// console.log('LiveConnect_pull--'+socket.uid+'-----'+pkpull);
						LiveConnect_pull[socket.uid] = pkpull;
						clientRedis.hset('LiveConnect_pull', socket.uid, pkpull);

						/* 更新数据库 */
						var sign_data = {uid: socket.uid, pkuid: pkuid, type: 1};
						var sign = setSign(sign_data);
						request(config['WEBADDRESS'] + "?service=Livepk.changeLive&uid=" + socket.uid + "&pkuid=" + pkuid + "&type=1&sign=" + sign, function (error, response, body) {
							// console.log('changeLive');
							// console.log(body);
						});

						/* 发送连麦成功信息 */
						/* 当前房间 */
						var data_obj = {
							"msg": [
								{
									"_method_": "LiveConnect",
									"action": "4",
									"msgtype": "10",
									"pkuid": "" + pkuid,
									"pkpull": "" + LiveConnect_pull[pkuid],
									"uid": "" + socket.uid,
									"uname": "" + socket.nicename
								}
							],
							"retcode": "000000",
							"retmsg": "OK"
						};
						// console.log(data_obj);
						process_msg(io, socket.roomnum, JSON.stringify(data_obj));

						/* 对方房间 */
						var data_obj_pk = {
							"msg": [
								{
									"_method_": "LiveConnect",
									"action": "4",
									"msgtype": "10",
									"pkuid": "" + socket.uid,
									"pkpull": "" + LiveConnect_pull[socket.uid],
									"uid": "" + socket.uid,
									"uname": "" + socket.nicename
								}
							],
							"retcode": "000000",
							"retmsg": "OK"
						};
						// console.log(data_obj_pk);
						process_msg(io, pkuid, JSON.stringify(data_obj_pk));
					} else if (action == '5') { //主播和主播断开连麦
						/* 清除连麦信息 */
						//console.log('endLiveConnect--action--5');
						endLiveConnect(io, socket.uid);
					} else {
						var socket_pkuid = sockets[pkuid];
						if (socket_pkuid) {
							socket_pkuid.emit('broadcastingListen', [data_str]);
						}
					}
					break;
				}
				//主播PK
				case 'LivePK': {
					if (socket.roomnum != socket.uid) {
						//非主播不能操作
						return !1;
					}
					var uid = msg['uid'];
					var pkuid = msg['pkuid'];
					//1：发起连麦；2；接受连麦;3:拒绝连麦;4：连麦成功通知;5.手动断开连麦;7:对方正忙碌 8:对方无响应; 9:PK结果
					if (action == '1') {
						// console.log('发起PK');
						// console.log(FormatNowDate());
						// console.log(socket.uid+'---'+pkuid);
					}
					if (action == '2') {
						/* 更新PK状态 */
						// console.log('LivePK');
						// console.log(socket.uid);
						// console.log(pkuid);
						// console.log('开始PK');
						// console.log(FormatNowDate());
						// console.log(socket.uid+'---'+pkuid);
						var sign_data = {uid: socket.uid, pkuid: pkuid};
						var sign = setSign(sign_data);
						request(config['WEBADDRESS'] + "?service=Livepk.setPK&uid=" + socket.uid + "&pkuid=" + pkuid + "&sign=" + sign, function (error, response, body) {
							if (error) return;
							// console.log('setPK');
							// console.log(body);
							var res = evalJson(body);
							if (response.statusCode == 200 && res.data.code == 0) {

								var info = res.data.info[0];
								// console.log('info');
								// console.log(info);
								/* 发送连麦成功信息 */
								/* 当前房间 */
								var data_obj = {
									"msg": [
										{
											"_method_": "LivePK",
											"action": "4",
											"msgtype": "10",
											"pkuid": "" + pkuid,
											"uid": "" + socket.uid,
											"uname": "" + socket.nicename
										}
									],
									"retcode": "000000",
									"retmsg": "OK"
								};

								process_msg(io, socket.roomnum, JSON.stringify(data_obj));
								/* 对方房间 */
								var data_obj_pk = {
									"msg": [
										{
											"_method_": "LivePK",
											"action": "4",
											"msgtype": "10",
											"pkuid": "" + socket.uid,
											"uid": "" + socket.uid,
											"uname": "" + socket.nicename
										}
									],
									"retcode": "000000",
									"retmsg": "OK"
								};
								process_msg(io, pkuid, JSON.stringify(data_obj_pk));

								setTimeout(function () {//定时发送结果
									// console.log('计时器');
									// console.log(FormatNowDate());
									// console.log('uid---'+socket.uid);
									endLivePk(io, socket.uid, 0, info['addtime']);
								}, 5 * 60 * 1000);
							}
						});
					} else if (action == '5') {
						/* 清除PK信息 */
						// console.log('endLivePk --action--5');
						// console.log(FormatNowDate());
						endLivePk(io, socket.uid, 1, 0);
					} else {
						var socket_pkuid = sockets[pkuid];
						if (socket_pkuid) {
							socket_pkuid.emit('broadcastingListen', [data_str]);
						}
						//process_msg(io,pkuid,data_str);
					}
					break;
				}
				//系统通知
				case 'SystemNot': {
					process_msg(io, socket.roomnum, data_str);
					break;
				}
				//上、下庄
				case 'shangzhuang': {
					process_msg(io, socket.roomnum, data_str);
					break;
				}
				//商品在直播间展示/不展示
				case 'goodsLiveShow': {
					process_msg(io, socket.roomnum, data_str);
					break;
				}
				//炸金花游戏
				case 'startGame': {
					process_msg(io, socket.roomnum, data_str);
					console.log("炸金花游戏开始的返回：", data_str);
					// 开始游戏的时候 定时发送倒计时
					/*let number = 15
					let st = setInterval(function () {
						data['msg'][0]['roomnum'] =  socket.roomnum
						data['msg'][0]['ct'] = number; // 倒计时的时间
						data['msg'][0]['_method_'] = "startGameTime";
						var data_str2 = JSON.stringify(data);
						process_msg(io, socket.roomnum, data_str2);
						number--
						if (number < 0) {
							console.log("炸金花游戏倒计时的返回：", data_str2);
							setTimeout(function () {
								clearInterval(st);
							}, 1000);
						}
					}, 1000);*/
					if (action == 4) {
						var time = msg['time'] * 1000;
						var gameid = msg['gameid'];
						setTimeout(function () {//定时发送结果
							request(config['WEBADDRESS'] + "?service=Game.endGame&liveuid=" + socket.uid + "&token=" + socket.token + "&gameid=" + gameid + "&type=1", function (error, response, body) {
								if (error) return;
								var res = evalJson(body);
								if (response.statusCode == 200 && res.data.code == 0) {
									var resObj = res.data.info;
									dataObj['msg'][0]['ct'] = resObj;
									dataObj['msg'][0]['_method_'] = "startGame";
									dataObj['msg'][0]['action'] = "6";
									var data_str2 = JSON.stringify(dataObj);
									process_msg(io, socket.roomnum, data_str2);
								}
							});
						}, time);
					}
					break;
				}
				//转盘
				case 'startRotationGame': {
					process_msg(io, socket.roomnum, data_str);
					if (action == 4) {
						var time = msg['time'] * 1000;
						var gameid = msg['gameid'];
						setTimeout(function () {//定时发送结果
							request(config['WEBADDRESS'] + "?service=Game.endGame&liveuid=" + socket.uid + "&token=" + socket.token + "&gameid=" + gameid + "&type=1", function (error, response, body) {
								if (error) return;
								//console.log(body);
								var res = evalJson(body);
								if (response.statusCode == 200 && res.data.code == 0) {
									var resObj = res.data.info;
									dataObj['msg'][0]['ct'] = resObj;
									dataObj['msg'][0]['_method_'] = "startRotationGame";
									dataObj['msg'][0]['action'] = "6";
									var data_str2 = JSON.stringify(dataObj);
									process_msg(io, socket.roomnum, data_str2);
								}
							});
						}, time);
					}
					break;
				}
				//开心牛仔
				case 'startCattleGame': {
					process_msg(io, socket.roomnum, data_str);
					if (action == 4) {
						var time = msg['time'] * 1000;
						var gameid = msg['gameid'];
						setTimeout(function () {//定时发送结果
							request(config['WEBADDRESS'] + "?service=Game.endGame&liveuid=" + socket.uid + "&token=" + socket.token + "&gameid=" + gameid + "&type=1", function (error, response, body) {
								if (error) return;
								var res = evalJson(body);

								if (response.statusCode == 200 && res.data.code == 0) {
									var resObj = res.data.info;
									dataObj['msg'][0]['ct'] = resObj;
									dataObj['msg'][0]['_method_'] = "startCattleGame";
									dataObj['msg'][0]['action'] = "6";
									var data_str2 = JSON.stringify(dataObj);
									process_msg(io, socket.roomnum, data_str2);
								}
							});
						}, time);
					}
					break;
				}
				//海盗船长
				case 'startLodumaniGame': {
					process_msg(io, socket.roomnum, data_str);
					if (action == 4) {
						var time = msg['time'] * 1000;
						var gameid = msg['gameid'];
						setTimeout(function () {//定时发送结果
							request(config['WEBADDRESS'] + "?service=Game.endGame&liveuid=" + socket.uid + "&token=" + socket.token + "&gameid=" + gameid + "&type=1", function (error, response, body) {
								if (error) return;
								var res = evalJson(body);

								if (response.statusCode == 200 && res.data.code == 0) {
									var resObj = res.data.info;
									dataObj['msg'][0]['ct'] = resObj;
									dataObj['msg'][0]['_method_'] = "startLodumaniGame";
									dataObj['msg'][0]['action'] = "6";
									var data_str2 = JSON.stringify(dataObj);
									process_msg(io, socket.roomnum, data_str2);
								}
							});
						}, time);
					}
					break;
				}
				//二八贝
				case 'startShellGame': {
					process_msg(io, socket.roomnum, data_str);
					if (action == 4) {
						var time = msg['time'] * 1000;
						var gameid = msg['gameid'];
						setTimeout(function () {//定时发送结果
							request(config['WEBADDRESS'] + "?service=Game.endGame&liveuid=" + socket.uid + "&token=" + socket.token + "&gameid=" + gameid + "&type=1", function (error, response, body) {
								if (error) return;
								var res = evalJson(body);
								if (response.statusCode == 200 && res.data.code == 0) {
									var resObj = res.data.info;
									dataObj['msg'][0]['ct'] = resObj;
									dataObj['msg'][0]['_method_'] = "startShellGame";
									dataObj['msg'][0]['action'] = "6";
									var data_str2 = JSON.stringify(dataObj);
									process_msg(io, socket.roomnum, data_str2);
								}
							});
						}, time);
					}
					break;
				}
				// （暂时未知）
				case 'requestFans': {
					request(config['WEBADDRESS'] + "?service=Live.getZombie&stream=" + socket.stream + "&uid=" + socket.uid, function (error, response, body) {
						if (error) return;
						var res = evalJson(body);
						//console.log(res);
						if (response.statusCode == 200 && res.data.code == 0) {
							var data_str2 = "{\"msg\":[{\"_method_\":\"requestFans\",\"action\":\"3\",\"ct\": " + body + ",\"msgtype\":\"0\"}],\"retcode\":\"000000\",\"retmsg\":\"OK\"}";
							process_msg(io, socket.roomnum, data_str2);
						}
					});
					break;
				}
				//直播间购物飘屏
				case 'shopGoodsLiveFloat': {
					process_msg(io, socket.roomnum, data_str);
					break;
				}
				//语音聊天室
				case 'voiceRoom': {
					process_msg(io, socket.roomnum, data_str);
					break;
				}

				// ##################################################################################################
				// 魔法召唤
				case 'startMagicGame': {
					process_msg(io, socket.roomnum, data_str);
					if (action == 4) {
						var time = msg['time'] * 1000;
						var gameid = msg['gameid'];
						setTimeout(function () { //定时发送结果
							// TODO 注意游戏的id action 或 type
							request(config['WEBADDRESS'] + "?service=Game.endGame&liveuid=" + socket.uid + "&token=" + socket.token + "&gameid=" + gameid + "&type=6", function (error, response, body) {
								if (error) return;
								//console.log(body);
								var res = evalJson(body);
								if (response.statusCode == 200 && res.data.code == 0) {
									var resObj = res.data.info;
									dataObj['msg'][0]['ct'] = resObj;
									dataObj['msg'][0]['_method_'] = "startRotationGame";
									dataObj['msg'][0]['action'] = "6";
									var data_str2 = JSON.stringify(dataObj);
									process_msg(io, socket.roomnum, data_str2);
								}
							});
						}, time);
					}
					break;
				}

				// 请求url并返回消息
				case 'sendUrlRequestRoomMsg':
					//case 'urlRequest':
					sendUrlRequestRoomMsg(socket, dataObj);
					break;

				// 发送房间消息
				case 'sendRoomMsg':
					process_msg(io, socket.roomnum, data_str);
					break;

				// 炸金花游戏：手动一次性开启
				case 'jinhuaLiveGame': {
					console.log('开启炸金花游戏，重新请求返回的数据', data_str)
					break;
				}
				case 'startJinhuaHand': {
					// 只有主播才开始游戏
					if (socket.roomnum == socket.uid) {
						console.log(socket.roomnum, socket.uid, '主播开启炸金花游戏')
					} else {
						var data_str5 = addReturn(data, "jinhuaLiveGame", '', '你不是主播不能开启游戏', -3);
						process_msg(io, socket.roomnum, data_str5);
						console.log(socket.roomnum, socket.uid, data_str5)
						break;
					}
					if (jinhua_interTime[socket.roomnum]) {
						var data_str2 = addReturn(data, "jinhuaLiveGame", '', '炸金花游戏已经开启', -1);
						process_msg(io, socket.roomnum, data_str2);
						console.log('炸金花游戏已经开启', data_str2)
						break;
					} else {
						// 避免报错的赋值
						jinhua_interTime[socket.roomnum] = {}
						jinhua_info[socket.roomnum] = {}
					}
					console.log('----------------------')
					// 6+16=22+3=25
					// 6+31=37+3=40
					setTimeout(function () {
						startJinhua(socket, data, 4, 30)
						jinhua_interval[socket.roomnum] = setInterval(function () {
							startJinhua(socket, data, 4, 30)
						}, 50000)
					}, 1000)

					break;
				}

				// 炸金花游戏：手动一次性结束
				case 'endJinhuaHand': {
					// 金花游戏：结束游戏
					if (jinhua_interval[socket.roomnum]) {
						setTimeout(function () {
							//定时发送结果
							if (jinhua_info[socket.roomnum]) {
								var _time = jinhua_info[socket.roomnum].time
								var _gameid = jinhua_info[socket.roomnum].gameid
								endJinhua(data, socket, _gameid, 2);
							}

							// 结束倒计时
							clearInterval(jinhua_interval[socket.roomnum]);
							delete jinhua_info[socket.roomnum]
						}, 1000);
					}

					// 金花游戏：结束游戏：如果金花游戏还没有开始
					// 取消定时任务：发牌、结束倒计时等
					if (jinhua_interTime[socket.roomnum]) {
						if (jinhua_interTime[socket.roomnum][2]) {
							clearInterval(jinhua_interTime[socket.roomnum][2]);
						}
						if (jinhua_interTime[socket.roomnum][1]) {
							clearInterval(jinhua_interTime[socket.roomnum][1]);
						}

						delete jinhua_interTime[socket.roomnum]
					}

					var data_str3 = addReturn(dataObj, "jinhuaLiveGameEnd", '', '炸金花游戏结束', 5);
					process_msg(io, socket.roomnum, data_str3);
					saveLog(data_str3);  // 保存日志

					break;
				}
			}
		}

	});

	// 超管关闭直播间
	socket.on('superadminaction', function (data) {
		if (data['token'] == config['TOKEN']) {
			io.sockets.in(data['roomnum']).emit("broadcastingListen", ['stopplay']);
		}
	});

	// 向客户端发送警告消息（只有config['TOKEN']的用户才能收到消息）
	socket.on('warning', function (data) {
		console.log('warning接收到的数据', data);
		if (data['token'] == config['TOKEN']) {
			var data_obj = {
				"msg": [
					{
						"_method_": "warning",
						"ct": "您已涉及违规,请立即改正否则将会关闭直播间"
					}
				],
				"retcode": "000000",
				"retmsg": "OK"
			};

			process_msg(io, data['roomnum'], JSON.stringify(data_obj));
		}
	});


	// 向所有的房间（或人）发送系统信息
	socket.on('systemadmin', function (data) {
		console.log('systemadmin接收到的数据', data);
		if (data['token'] == config['TOKEN']) {
			sendAdminMsg(io, data.content)
		}
	});

	//资源释放（断开链接）
	socket.on('disconnect', function () {
		// console.log(FormatNowDate());
		// console.log('disconnect');
		/* numscount--;
		if(numscount<0){
			numscount=0;
		}   */

		if (socket.roomnum == null || socket.token == null || socket.uid <= 0 || socket.isvideo == 1) {
			return !1;
		}
		console.log('断开游戏：是否是虚拟视频', socket.isvideo)

		d.run(function () {
			/* 用户连麦 */
			clientRedis.hget('ShowVideo', socket.roomnum, function (error, res) {
				if (error) {
					return !1;
				}
				if (!res) {
					return !1;
				}
				var res_j = JSON.parse(res);
				if (socket.uid == res_j['uid'] || socket.uid == socket.roomnum) {
					clientRedis.hdel('ShowVideo', socket.roomnum);
					var data_obj = {
						"msg": [
							{
								"_method_": "ConnectVideo",
								"action": "5",
								"msgtype": "10",
								"uid": "" + socket.uid,
								"uname": "" + socket.nicename
							}
						],
						"retcode": "000000",
						"retmsg": "OK"
					};
					process_msg(io, socket.roomnum, JSON.stringify(data_obj));
				}
			});

			if (socket.roomnum == socket.uid) {
				/* 主播 */
				if (socket.reusing == 0) {
					var data_obj = {
						"retmsg": "ok",
						"retcode": "000000",
						"msg": [
							{
								"msgtype": "1",
								"_method_": "StartEndLive",
								"action": "18",
								"ct": "直播关闭"
							}
						]
					};

					request(config['WEBADDRESS'] + "?service=Live.stopRoom&uid=" + socket.uid + "&token=" + socket.token + "&type=1&source=socket&stream=" + socket.stream, function (error, response, body) {
						process_msg(io, socket.roomnum, JSON.stringify(data_obj));
						// console.log('关播');
						// console.log(FormatNowDate());
						// console.log('uid---'+socket.uid);
					});
					endLiveConnect(io, socket.uid);

					// 金花游戏：结束游戏
					if (jinhua_interval[socket.roomnum]) {
						setTimeout(function () {
							//定时发送结果
							if (jinhua_info[socket.roomnum]) {
								var _time = jinhua_info[socket.roomnum].time
								var _gameid = jinhua_info[socket.roomnum].gameid
								endJinhua(data_obj, socket, _gameid, 3);
							}

							// 结束倒计时
							clearInterval(jinhua_interval[socket.roomnum]);
							delete jinhua_info[socket.roomnum]
						}, 1000);
					}
					// 金花游戏：结束游戏：如果金花游戏还没有开始
					// 取消定时任务：发牌、结束倒计时等
					console.log('主播断开，关闭游戏', jinhua_interTime[socket.roomnum]);
					if (jinhua_interTime[socket.roomnum]) {
						if (jinhua_interTime[socket.roomnum][2]) {
							clearInterval(jinhua_interTime[socket.roomnum][2]);
						}
						if (jinhua_interTime[socket.roomnum][1]) {
							clearInterval(jinhua_interTime[socket.roomnum][1]);
						}

						delete jinhua_interTime[socket.roomnum]
					}
				}
			} else {
				/* 观众 */
				clientRedis.zrem('user_' + socket.stream, socket.uid, function (error, res) {
					if (error) return;
					if (res) {
						//用于每日任务--用户观看直播时长统计
						request(config['WEBADDRESS'] + "?service=Live.signOutWatchLive&uid=" + socket.uid + "&token=" + socket.token, function (error, response, body) {
						});
						var data_obj = {
							"msg": [
								{
									"_method_": "disconnect",
									"action": "1",
									"ct": {
										"id": '' + socket.uid,
										"user_nickname": '' + socket.nickname,
										"avatar": socket.avatar,
										"level": '' + socket.level
									},
									"msgtype": "0",
									"uid": '' + socket.uid,
									"uname": socket.nicename
								}
							],
							"retcode": "000000",
							"retmsg": "OK"
						};
						process_msg(io, socket.roomnum, JSON.stringify(data_obj));
					}
				});

				clientRedis.del(socket.token);
				clientRedis.hdel('super', socket.uid);

				//用户退出房间要将上麦记录删除
				request(config['WEBADDRESS'] + "?service=Live.userCloseVoiceMic&uid=" + socket.uid + "&token=" + socket.token + "&stream=" + socket.stream, function (error, response, body) {
				});
				var data_obj = {
					"msg": [
						{
							"_method_": "voiceRoom",
							"action": "3",
							"uid": '' + socket.uid,
							"type": "0"
						}
					],
					"retcode": "000000",
					"retmsg": "OK"
				};
				process_msg(io, socket.roomnum, JSON.stringify(data_obj));
			}
			//console.log(socket.roomnum+"==="+socket.token+"===="+socket.uid+"======"+socket.stream);

			socket.leave(socket.roomnum);
			delete io.sockets.sockets[socket.id];
			sockets[socket.uid] = null;
			delete sockets[socket.uid];
		});
	});

});


// 制作返回的消息
function makeReturn(info, method, ct, commit = '', action = 0) {
	info['_method_'] = method
	info['ct'] = ct
	info['action'] = action
	info['commit'] = commit
	return JSON.stringify({"msg": [info], "retcode": "000000", "retmsg": "OK"});
}

// 制作返回的消息
function addReturn(dataObj, method, ct, commit = '', action = 0) {
	dataObj['msg'][0]['ct'] = ct;
	dataObj['msg'][0]['_method_'] = method;
	dataObj['msg'][0]['action'] = action;
	dataObj['msg'][0]['commit'] = commit;
	return JSON.stringify(dataObj);
}

// 请求url并返回数据
function sendUrlRequestRoomMsg(socket, dataObj) {
	let data_str2;
	let _url = config['WEBADDRESS'] + '?';
	if (!dataObj['msg'] || !dataObj['msg'][0] || !dataObj['msg'][0]['param']) {
		data_str2 = addReturn(dataObj, "urlRequest", '请传递请求的参数', '请求url并返回数据');
		process_msg(io, socket.roomnum, data_str2);
		return false;
	}


	// 参数
	//_url = config['WEBADDRESS'] + "?service=Game.settleGame&uid=" + socket.uid + "&token=" + socket.token + "&gameid=" + gameid;
	for (let it in dataObj['msg'][0]['param']) {
		_url += it + '=' + dataObj['msg'][0]['param'][it] + '&';
	}

	console.log('请求地址', _url)
	request(_url, function (error, response, body) {
		if (error) {
			console.log(error)
			return;
		}
		var res = evalJson(body);
		if (response.statusCode == 200 && res.data.code == 0) {
			data_str2 = addReturn(dataObj, "urlRequest", res.data.info, '请求url并返回数据');
			process_msg(io, socket.roomnum, data_str2);
		} else {
			data_str2 = addReturn(dataObj, "urlRequest", res.data, '请求url返回数据错误');
			process_msg(io, socket.roomnum, data_str2);
		}
	});
}

// 保存日志
function saveLog(data) {
	//console.log('发送日志', config['WEBADDRESS'] + "?service=Home.nodeLog&data="+ encodeURIComponent(data))
	request(config['WEBADDRESS'] + "?service=Home.nodeLog&data=" + encodeURIComponent(data), function (error, response, body) {
		if (error) {
			console.log(error)
			return;
		}
	});
}

// 发送系统消息（应该收到的是所有的直播间）
function sendAdminMsg(io, msg) {
	var data_obj = {
		"msg": [
			{
				"_method_": "SystemNot",
				"action": "1",
				"ct": '' + msg,
				"msgtype": "4"
			}
		],
		"retcode": "000000",
		"retmsg": "OK"
	};

	io.emit('broadcastingListen', [JSON.stringify(data_obj)]);
}

// 发送系统消息（应该收到的是当前的某个人）
function sendSystemMsg(socket, msg) {
	var data_obj = {
		"msg": [
			{
				"_method_": "SystemNot",
				"action": "1",
				"ct": "" + msg,
				"msgtype": "4"
			}
		],
		"retcode": "000000",
		"retmsg": "OK"
	};

	socket.emit('broadcastingListen', [JSON.stringify(data_obj)]);
}

// json字符串为数组
function evalJson(data) {
	return eval("(" + data + ")");
}

// 发送消息：（向某个房间发送消息）
// 如果有还未发送的消息，将这个消息保存起来，在发送
function process_msg(io, roomnum, data) {
	if (!chat_history[roomnum]) {
		chat_history[roomnum] = [];
	}
	chat_history[roomnum].push(data);
	chat_interval[roomnum] || (chat_interval[roomnum] = setInterval(function () {
		if (chat_history[roomnum].length > 0) {
			send_msg(io, roomnum);
		} else {
			clearInterval(chat_interval[roomnum]);
			chat_interval[roomnum] = null;
		}
	}, 200));
}

// 发送消息：（向某个房间发送消息）（从需要发送的消息中取出一条消息来发送）
function send_msg(io, roomnum) {
	var data = chat_history[roomnum].splice(0, chat_history[roomnum].length);
	io.sockets.in(roomnum).emit("broadcastingListen", data);
}

// 主播连麦结束处理
function endLiveConnect(io, uid) {
	//console.log('结束连麦');
	//console.log(FormatNowDate());
	//console.log('uid--'+uid);
	clientRedis.hget('LiveConnect', uid, function (error, res) {
		//console.log('res');
		if (error) {
			return !1;
		}
		if (!res) {
			return !1;
		}
		var pkuid = res;
		//console.log('pkuid---'+pkuid);
		/* 更新数据库 */
		var sign_data = {uid: uid, pkuid: pkuid, type: 0};
		var sign = setSign(sign_data);
		request(config['WEBADDRESS'] + "?service=Livepk.changeLive&uid=" + uid + "&pkuid=" + pkuid + "&type=0&sign=" + sign, function (error, response, body) {
			if (error) return;
			//console.log('changeLive');
			//console.log(body);
			var res = evalJson(body);
			if (response.statusCode == 200 && res.data.code == 0) {
				var data_obj = {
					"msg": [
						{
							"_method_": "LiveConnect",
							"action": "5",
							"msgtype": "10",
							"uid": "" + uid,
							"uname": ""
						}
					],
					"retcode": "000000",
					"retmsg": "OK"
				};

				process_msg(io, uid, JSON.stringify(data_obj));
				process_msg(io, pkuid, JSON.stringify(data_obj));
			}
		});
	});
}

// PK结束处理
function endLivePk(io, uid, type, addtime) {
	// console.log('结束PK');
	// console.log('uid-'+uid);
	// console.log('addtime-'+addtime);
	// console.log('type-'+type);
	var sign_data = {uid: uid, addtime: addtime, type: type};
	var sign = setSign(sign_data);
	request(config['WEBADDRESS'] + "?service=Livepk.endPK&uid=" + uid + "&addtime=" + addtime + "&type=" + type + "&sign=" + sign, function (error, response, body) {
		if (error) return;
		// console.log('endPK');
		// console.log(body);
		var res = evalJson(body);
		if (response.statusCode == 200 && res.data.code == 0) {
			var info = res.data.info[0];
			var data_obj = {
				"msg": [
					{
						"_method_": "LivePK",
						"action": "9",
						"msgtype": "10",
						"win_uid": "" + info['win_uid'],
						"uid": "" + uid,
						"uname": ""
					}
				],
				"retcode": "000000",
				"retmsg": "OK"
			};

			process_msg(io, uid, JSON.stringify(data_obj));
			process_msg(io, info['pkuid'], JSON.stringify(data_obj));
		}
	});
}

//时间格式化
function FormatNowDate() {
	var mDate = new Date();
	var Y = mDate.getFullYear();
	var M = mDate.getMonth() + 1;
	var D = mDate.getDate();
	var H = mDate.getHours();
	var i = mDate.getMinutes();
	var s = mDate.getSeconds();
	return Y + '-' + M + '-' + D + ' ' + H + ':' + i + ':' + s;
}

// sign加密
function setSign(obj) {//排序的函数
	var str = '';
	var newkey = Object.keys(obj).sort();
	//先用Object内置类的keys方法获取要排序对象的属性名，再利用Array原型上的sort方法对获取的属性名进行排序，newkey是一个数组
	var newObj = {};//创建一个新的对象，用于存放排好序的键值对
	for (var i = 0; i < newkey.length; i++) {//遍历newkey数组
		//newObj[newkey[i]] = obj[newkey[i]];//向新创建的对象中按照排好的顺序依次增加键值对
		str += newkey[i] + '=' + obj[newkey[i]] + '&';
	}
	str += config['sign_key'];
	var sign = md5(str);

	return sign;
}

//过滤函数
function filter(str) {
	// 多个敏感词，这里直接以数组的形式展示出来
	var arrMg = field;
	//console.log(arrMg);
	// 显示的内容--showContent
	var showContent = str;
	//console.log(showContent);
	// 正则表达式
	// \d 匹配数字

	for (var i = 0; i < arrMg.length; i++) {
		// 创建一个正则表达式
		var r = new RegExp(arrMg[i], "ig");
		var re = '';
		for (var n = 0; n < arrMg[i].length; n++) {
			re += '*';
		}
		showContent = showContent.replace(r, re);
	}

	// 显示的内容--showInput
	//console.log(showContent);
	return showContent;
}

// 定时器消息:定次数发送消息
function timeMessage(io, roomnum, data, _method_, number = 15) {
	let st = setInterval(function () {
		var data_str2 = addReturn(data, _method_, number, '倒计时时间');
		process_msg(io, roomnum, data_str2);

		number--
		if (number < 0) {
			// 结束倒计时
			setTimeout(function () {
				clearInterval(st);
			}, 1000);
		}
	}, 1000);
}

// 结束金花游戏
function endJinhua(dataObj, socket, gameid, type = 1) {
	//定时发送结果
	let _url = config['WEBADDRESS'] + "?service=Game.endGame&liveuid=" + socket.uid + "&token=" + socket.token + "&gameid=" + gameid + "&type=" + type;

	console.log('结束游戏id' + gameid)
	request(_url, function (error, response, body) {
		if (error) return;
		var res = evalJson(body);
		if (response.statusCode == 200 && res.data.code == 0) {
			var data_str2 = addReturn(dataObj, "jinhuaLiveGame", res.data.info, '炸金花游戏结束', 5);
			process_msg(io, socket.roomnum, data_str2);
			console.log('炸金花游戏结束', data_str2)
			saveLog(data_str2);  // 保存日志
		} else {
			console.log('直播间游戏结束失败', res)
		}
	});
}

// 游戏结算（暂无使用，应该是客户端来调用）
function settleGame(socket, gameid) {
	//定时发送结果
	let _url = config['WEBADDRESS'] + "?service=Game.settleGame&uid=" + socket.uid + "&token=" + socket.token + "&gameid=" + gameid;
	request(_url, function (error, response, body) {
		if (error) return;
		var res = evalJson(body);
		if (response.statusCode == 200 && res.data.code == 0) {
			var resObj = res.data.info;
			var data_str2 = addReturn(dataObj, "settleGame", resObj, '游戏结算');

			process_msg(io, socket.roomnum, data_str2);
		}
	});
}

// 开始金花游戏（根据客户单请求逻辑完成）
/**
 * 使用定时器完成所有的逻辑
 * 金花游戏action
 * 1 - 开启游戏：1秒：
 * 2 - 开始游戏倒计时：5秒
 * 3 - 准备游戏：2秒：返回一个提示（开始游戏）
 * 4 - 游戏倒计时：15秒
 * 5 - 游戏结束：返回一个提示（开始游戏）（大概3-5秒，时间待定）
 *  - 游戏结算：以前的请求方式进行
 */
function startJinhua(socket, data, time1 = 5, time2 = 30) {
	let _url = config['WEBADDRESS'] + "?service=Game.Jinhua&liveuid=" + socket.uid + "&token=" + socket.token + "&stream=" + socket.stream + "&from=server_js";

	// 操作1：发牌倒计时开始
	var data_str1 = addReturn(data, "jinhuaLiveGame", '', '发牌倒计时开始', 1);
	process_msg(io, socket.roomnum, data_str1);
	saveLog(data_str1);  // 保存日志

	// 操作2、假倒计时：发牌后1s执行
	setTimeout(function () {
		setTimeout(function () {
			// 倒计时可能被外面停止了
			if (jinhua_interTime[socket.roomnum]) {
				clearInterval(jinhua_interTime[socket.roomnum][1]);
			}
		}, time1 * 1000 + 1500);

		// 避免报错的赋值
		if (!jinhua_interTime[socket.roomnum]) {
			jinhua_interTime[socket.roomnum] = {}
		}
		jinhua_interTime[socket.roomnum][1] = setInterval(function () {
			var data_str1 = addReturn(data, "jinhuaLiveGame", time1 + 1, '炸金花游戏开始前：倒计时', 2);
			process_msg(io, socket.roomnum, data_str1);
			console.log('炸金花游戏开始前：倒计时', data_str1)
			time1--

			// TODO 如果为负  则结束倒计时
			if (time1 < -1) {
				setTimeout(function () {
					// 倒计时可能被外面停止了
					if (jinhua_interTime[socket.roomnum]) {
						clearInterval(jinhua_interTime[socket.roomnum][1]);
					}
				}, 1500);
			}

		}, 1000);
	}, 1000)


	// 操作3：假倒计时结束：准备游戏，开始游戏
	setTimeout(function () {
		if (time1 < 0) {
			console.log('结束假倒计时，开启游戏', _url)
			// 开启游戏：启动结束的倒计时
			request(_url, function (error, response, body) {
				if (error) return;
				var res = evalJson(body);
				if (response.statusCode == 200 && res.data.code == 0) {
					// 开启游戏操作
					//console.log('开启游戏', res.data.info[0])
					var gameinfo = res.data.info[0];
					var gameid = res.data.info[0].gameid;
					var time = parseInt(res.data.info[0].time) * 1000;

					if (!jinhua_info[socket.roomnum]) {
						jinhua_info[socket.roomnum] = {}
					}
					jinhua_info[socket.roomnum].time = time;
					jinhua_info[socket.roomnum].gameid = gameid;

					// 操作3：发送开始游戏的通知消息
					data['msg'][0]['gameid'] = gameid;
					var data_str2 = addReturn(data, "jinhuaLiveGame", '', '炸金花游戏正式开始', 3);
					process_msg(io, socket.roomnum, data_str2);
					console.log('炸金花游戏正式开始', data_str2)
					saveLog(data_str2);  // 保存日志

					// 操作4：游戏倒计时：15秒
					// 3s后开启结束倒计时
					// 如果没有了 则说明被结束了
					if (jinhua_interTime[socket.roomnum]) {
						// 结束倒计时的发送
						setTimeout(function () {
							// 结束倒计时
							if (jinhua_interTime[socket.roomnum]) {
								clearInterval(jinhua_interTime[socket.roomnum][2]);
							}
							//定时发送结果
							endJinhua(data, socket, gameid, 1);
						}, time2 * 1000 + 1500 + 3000);


						// 开始游戏的时候 定时发送倒计时
						setTimeout(function () {
							if (!jinhua_interTime[socket.roomnum]) {
								jinhua_interTime[socket.roomnum] = {}
							}

							// 发送：执行结束倒计时
							jinhua_interTime[socket.roomnum][2] = setInterval(function () {
								var data_str2 = addReturn(data, "jinhuaLiveGame", time2, '炸金花游戏：结束倒计时', 4);
								process_msg(io, socket.roomnum, data_str2);
								console.log('炸金花游戏开始：结束倒计时', data_str2)
								time2--

								// TODO 如果为负  则结束倒计时
								if (time2 < -1) {
									// 结束倒计时的发送
									setTimeout(function () {
										// 结束倒计时
										if (jinhua_interTime[socket.roomnum]) {
											clearInterval(jinhua_interTime[socket.roomnum][2]);
										}
										//定时发送结果
										endJinhua(data, socket, gameid, 1);
									}, 1500);
								}

							}, 1000);
						}, 3000)
					}
				} else {
					console.log('开启游戏失败', res)
					if (res.data.code != 0) {
						var data_str4 = addReturn(data, "jinhuaLiveGame", res.data.msg, '炸金花游戏：开启失败', -2);
						process_msg(io, socket.roomnum, data_str4);
						saveLog(data_str4);  // 保存日志
					}
					clearInterval(jinhua_interTime[socket.roomnum]);
					// 如果是没有结束游戏 则结束游戏
					if (res.data.code == 1000) {
						endJinhua(data, socket, res.data.info.id, 3);
					}
				}
			});
		}
	}, 2000 + time1 * 1000 + 1500);

}


/**
 * 不使用定时器完成所有的逻辑（使用循环完成所有的逻辑）
 * 金花游戏action
 * 1 - 开启游戏：1秒：
 * 2 - 开始游戏倒计时：5秒
 * 3 - 准备游戏：2秒：返回一个提示（开始游戏）
 * 4 - 游戏倒计时：15秒
 * 5 - 游戏结束：返回一个提示（开始游戏）（大概3-5秒，时间待定）
 *  - 游戏结算：以前的请求方式进行
 */
function startJinhuaLoop(socket, data, times1 = 5, times2 = 30) {
	let _url = config['WEBADDRESS'] + "?service=Game.Jinhua&liveuid=" + socket.uid + "&token=" + socket.token + "&stream=" + socket.stream + "&from=server_js";

	// 操作1：发牌倒计时开始
	var data_str1 = addReturn(data, "jinhuaLiveGame", '', '发牌倒计时开始', 1);
	process_msg(io, socket.roomnum, data_str1);

	// 如果游戏被停止
	if (jinhua_interTime[socket.roomnum] === undefined) {
		return
	}
	// 赋值游戏时间
	let time_start = 1;   // 1、开启游戏时间
	let time_runup = 3;   // 3、准备游戏时间
	let time_end = 3;   // 5、游戏结束，等待前端页面动画显示
	jinhua_interTime[socket.roomnum][1] = times1
	jinhua_interTime[socket.roomnum][2] = times2


	// 操作2、假倒计时：发牌后1s执行
	setTimeout(function () {
		for (var ii = 0; ii < times1; ii++) {
			setTimeout(function () {
				// 如果倒计时没有被停止 则发送倒计时
				//   可能会在外面关闭游戏等操作停止倒计时
				try {
					if (jinhua_interTime[socket.roomnum] && jinhua_interTime[socket.roomnum][1]) {
						var data_str1 = addReturn(data, "jinhuaLiveGame", jinhua_interTime[socket.roomnum][1], '炸金花游戏开始前：倒计时', 2);
						process_msg(io, socket.roomnum, data_str1);
						console.log('炸金花游戏开始前：倒计时', data_str1)
						// 用于下一次发牌倒计时
						jinhua_interTime[socket.roomnum][1]--
					}
				} catch (error) {
					console.log('抛出异常: ', error.message);
				}
			}, 1000 * ii)
		}
	}, time_start * 1000)


	// 操作3：假倒计时结束：准备游戏，开始游戏
	setTimeout(function () {
		try {
			console.log('结束假倒计时，开启游戏', _url)
			request(_url, function (error, response, body) {
				if (error) return;
				var res = evalJson(body);
				if (response.statusCode == 200 && res.data.code == 0) {
					// 如果没有了 则说明被结束了
					if (!jinhua_interTime[socket.roomnum]) {
						return;
					}

					// 开启游戏操作
					//console.log('开启游戏', res.data.info[0])
					var gameinfo = res.data.info[0];
					var gameid = res.data.info[0].gameid;
					var time = parseInt(res.data.info[0].time) * 1000;

					// 用于断开的时候自动关闭游戏
					if (!jinhua_info[socket.roomnum]) {
						jinhua_info[socket.roomnum] = {}
					}
					jinhua_info[socket.roomnum].time = time;
					jinhua_info[socket.roomnum].gameid = gameid;

					// 操作3：发送开始游戏的通知消息
					data['msg'][0]['gameid'] = gameid;
					var data_str2 = addReturn(data, "jinhuaLiveGame", '', '炸金花游戏正式开始', 3);
					process_msg(io, socket.roomnum, data_str2);
					console.log('炸金花游戏正式开始', data_str2)

					// 操作4：游戏倒计时：15秒
					// 3s后开启发送结束倒计时
					setTimeout(function () {
						for (var ii = 0; ii < times2; ii++) {
							setTimeout(function () {
								// 发送：执行结束倒计时
								//   可能会在外面关闭游戏等操作停止倒计时
								try {
									if (jinhua_interTime[socket.roomnum] && jinhua_interTime[socket.roomnum][2]) {
										var data_str2 = addReturn(data, "jinhuaLiveGame", time2, '炸金花游戏：结束倒计时', 4);
										process_msg(io, socket.roomnum, data_str2);
										console.log('炸金花游戏开始：结束倒计时', data_str2)
										// 用于下一次发牌倒计时
										jinhua_interTime[socket.roomnum][2]--
									}
								} catch (error) {
									console.log('抛出异常: ', error.message);
								}
							}, 1000 * ii)
						}
					}, time_runup * 1000)

					// 结束倒计时结束后结束游戏
					setTimeout(function () {
						endJinhua(data, socket, gameid, 1);
					}, (times2 + time_runup) * 1000 + 500);

				} else {
					console.log('开启游戏失败', res)
					// 发送给前台用户
					if (res.data.code != 0) {
						var data_str4 = addReturn(data, "jinhuaLiveGame", res.data.msg, '炸金花游戏：开启失败', -2);
						process_msg(io, socket.roomnum, data_str4);
					}
					// 如果是没有结束游戏 则结束游戏
					if (res.data.code == 1000) {
						endJinhua(data, socket, res.data.info.id, 3);
					}
					if (jinhua_interTime[socket.roomnum]) {
						jinhua_interTime[socket.roomnum][2] = 0;
					}
					// 重启游戏
					console.log('5s后重启游戏')
					setTimeout(function () {
						startJinhuaLoop(socket, data, times1, times2)
					}, 5000)
				}
			});
		} catch (error) {
			console.log('开启游戏抛出异常: ', error.message);
		}
	}, (time_start + times1) * 1000 + 500);

	// 如果游戏未关闭 6秒后继续执行游戏
	setTimeout(function () {
		if (jinhua_interTime[socket.roomnum]) {
			startJinhuaLoop(socket, data, times1, times2)
		}
	}, (time_start + time_runup + time_end + times1 + times2) * 1000)
}


/**
 *
 * 金花游戏action
 * 1 - 开启游戏：1秒：没有返回
 * 2 - 开始游戏倒计时：5秒
 * 3 - 准备游戏：1秒：返回一个提示（开始游戏）
 * 4 - 游戏倒计时：15秒
 * 5 - 游戏结束：返回一个提示（开始游戏）（大概3-5秒，时间待定）
 *  - 游戏结算：以前的请求方式进行
 */
function startJinhua2(socket, data, time1 = 5, time2 = 30) {
	let _url = config['WEBADDRESS'] + "?service=Game.Jinhua&liveuid=" + socket.uid + "&token=" + socket.token + "&stream=" + socket.stream + "&from=server_js";

	// 发牌倒计时开始
	var data_str1 = addReturn(data, "jinhuaLiveGame", '', '发牌倒计时开始', 1);
	process_msg(io, socket.roomnum, data_str1);

	// 避免报错的赋值
	if (!jinhua_interTime[socket.roomnum]) {
		jinhua_interTime[socket.roomnum] = {}
	}

	// 假倒计时
	jinhua_interTime[socket.roomnum][1] = setInterval(function () {
		var data_str1 = addReturn(data, "jinhuaLiveGame", time1, '炸金花游戏开始前：倒计时', 2);
		process_msg(io, socket.roomnum, data_str1);
		console.log('炸金花游戏开始前：倒计时', data_str1)

		time1--
		if (time1 < 0) {
			// 结束：假倒计时结束：2秒后开始游戏
			setTimeout(function () {
				console.log('结束假倒计时，开启游戏', _url)
				// 倒计时可能被外面停止了
				if (jinhua_interTime[socket.roomnum]) {
					clearInterval(jinhua_interTime[socket.roomnum][1]);
				}

				// 开启游戏
				request(_url, function (error, response, body) {
					if (error) return;
					var res = evalJson(body);
					if (response.statusCode == 200 && res.data.code == 0) {
						// 开启游戏操作
						//console.log('开启游戏', res.data.info[0])
						var gameinfo = res.data.info[0];
						var gameid = res.data.info[0].gameid;
						var time = parseInt(res.data.info[0].time) * 1000;

						if (!jinhua_info[socket.roomnum]) {
							jinhua_info[socket.roomnum] = {}
						}
						jinhua_info[socket.roomnum].time = time;
						jinhua_info[socket.roomnum].gameid = gameid;

						// 发送开始游戏的通知消息
						data['msg'][0]['gameid'] = gameid;
						var data_str2 = addReturn(data, "jinhuaLiveGame", '', '炸金花游戏正式开始', 3);
						process_msg(io, socket.roomnum, data_str2);
						console.log('炸金花游戏正式开始', data_str2)

						// 如果没有了 则说明被结束了
						if (jinhua_interTime[socket.roomnum]) {
							setTimeout(function () {
								// 开始游戏的时候 定时发送倒计时
								if (!jinhua_interTime[socket.roomnum]) {
									jinhua_interTime[socket.roomnum] = {}
								}
								jinhua_interTime[socket.roomnum][2] = setInterval(function () {
									var data_str2 = addReturn(data, "jinhuaLiveGame", time2, '炸金花游戏：结束倒计时', 4);
									process_msg(io, socket.roomnum, data_str2);
									console.log('炸金花游戏开始前：倒计时', data_str2)

									time2--
									if (time2 < 0) {
										setTimeout(function () {
											//console.log('直播间游戏开始：真倒计时结束')
											// 结束倒计时
											if (jinhua_interTime[socket.roomnum]) {
												clearInterval(jinhua_interTime[socket.roomnum][2]);
											}
											//定时发送结果
											endJinhua(data, socket, gameid, 1);
										}, 1000);
									}
								}, 1000);
							}, 3000)
						}
					} else {
						console.log('开启游戏失败', res)
						clearInterval(jinhua_interTime[socket.roomnum]);
						clearInterval(jinhua_interval[socket.roomnum]);
						// 如果是没有结束游戏 则结束游戏
						if (res.data.code == 1000) {
							endJinhua(data, socket, res.data.info.id, 3);
						}
					}
				});

			}, 1000);
		}
	}, 1000);
}


